home *** CD-ROM | disk | FTP | other *** search
/ CYBER.XPO.95 / CYBER.XPO.95 (Arsenal Computer).ISO / popreq / amiga1 / a1000hks.lha / ykick / yKick.c < prev    next >
C/C++ Source or Header  |  1993-02-28  |  7KB  |  296 lines

  1. /*
  2.  *  yKick.c
  3.  *
  4.  *  (c)Copyright 1992,93 by Tobias Ferber,  All Rights Reserved.
  5.  */
  6.  
  7. #include <exec/types.h>
  8. #include <exec/memory.h>
  9. #include <fcntl.h>
  10. #include <stdio.h>
  11.  
  12. /* default values */
  13. #define KICKORG  0x200000
  14. #define KICKWOM  0xF80000 /* 0xFC0000 */
  15. #define KICKSIZE (512*1024)
  16.  
  17. extern void reset(long,long);
  18. extern void patch(long,long,long,long,long);
  19.  
  20. static char rcs_id[]= "$VER: $Id: ykick.c,v 1.1 93/02/25 01:15:08 tf Exp $";
  21. #define BANNER &rcs_id[6]
  22.  
  23. /*
  24.  *   kickload -- load a ZKick file to a fix address
  25.  *   result is 0 in case of an error, != 0 otherwise
  26.  */
  27.  
  28. int kickload(char *fname, long fmem)  /* 0= error */
  29. {
  30.   int ok= 0,
  31.       fh= open(fname,O_RDONLY);
  32.  
  33.   if(fh >= 0)
  34.   { long fsize;
  35.     fsize= lseek(fh,0,SEEK_END);
  36.     if(fsize==KICKSIZE+8)
  37.     { printf("Loading \"%s\" (%ld-8 bytes) to $%06lx, ",fname,fsize,fmem);
  38.       fflush(stdout);
  39.       lseek(fh,8,SEEK_SET); /* skip 0x00000000, 0x00080000 header */
  40.       ok= read(fh,(void *)fmem,fsize-8);
  41.       if(ok==fsize-8) puts("ok.");
  42.       else
  43.       { puts("error.");
  44.         ok=0;
  45.       }
  46.     }
  47.     else puts("Failure -- File is not A2000/500 Kickstart V37.175");
  48.     close(fh);
  49.   }
  50.   else printf("Can't open %s\n",fname);
  51.  
  52.   return(ok);
  53. }
  54.  
  55. /*
  56.  *   kicksave -- save a A1000 kickstart file
  57.  *   result is 0 in case of an error, != 0 otherwise
  58.  */
  59.  
  60. int kicksave(char *fname, long fmem)
  61. {
  62.   int ok= 1,
  63.       fh= open(fname,O_RDONLY);
  64.    
  65.   if(fh >= 0)
  66.   { char c;
  67.     close(fh);
  68.     printf("\"%s\" already exists, overwrite? (Y/n): ",fname);
  69.     fflush(stdout);
  70.     c= getchar();
  71.     if(c=='n' && c=='N')
  72.       ok=0;
  73.   }
  74.  
  75.   if(ok)
  76.   { fh= open(fname,O_WRONLY|O_CREAT);
  77.     if(fh >= 0)
  78.     { printf("Writing \"%s\" (%ld bytes) ",fname,KICKSIZE);
  79.       fflush(stdout);
  80.       ok= write(fh,(void *)fmem,KICKSIZE);
  81.       if(ok==KICKSIZE) puts("ok.");
  82.       else
  83.       { puts("error.");
  84.         ok=0;
  85.       }
  86.       close(fh);
  87.     }
  88.     else
  89.     { printf("Can't open %s\n",fname);
  90.       ok=0;
  91.     }
  92.   }
  93.   return(ok);
  94. }
  95.  
  96. /*
  97.  *   reloc -- relocate a ZKick file for A1000 usage
  98.  *
  99.  *   The Kickfile loaded to 'loadmem' will be relocated using
  100.  *   Daniel Zenchelsky's kickfile reloc table.  The lower 256k
  101.  *   will be relocated to 'kickmem' -- the upper 256k to $fc0000
  102.  */
  103.  
  104. void reloc(char *mem,  /* current location of the kickfile */
  105.            long kick)  /* absolute memory origin 1st part */
  106. {
  107.   extern long rtable[]; /* ZKick relocation table */
  108.  
  109.   long r;  /* index for rtable[] */
  110.   long *v;
  111.  
  112.   for(r=0; rtable[r]!=0; r++)
  113.   { v= (long *)&mem[rtable[r]];
  114.     *v-= KICKORG;
  115.     if(*v<0x40000) *v+=kick;
  116.     else *v+=KICKWOM;
  117.   }
  118. }
  119.  
  120. /*
  121.  *   checksum -- compute the kickstart checksum
  122.  */
  123.  
  124. long checksum(long *mem,      /* beg. of memory block */
  125.               long numbytes)  /* must be a multiple of 4 */
  126. {
  127.   unsigned long s,t;
  128.  
  129.   for(s=0;numbytes>0;numbytes-=4)
  130.   { t=s;
  131.     s+=*mem++;
  132.     if(s<t) ++s;
  133.   }
  134.   return(s^0xFFFFFFFF);
  135. }
  136.  
  137.  
  138. static char *howtouse[]= {
  139.  "KICKFILE",   "/K", "-f", "force next argument to be the kickfile",
  140.  "START",      "/N", "-s", "set begin of fast memory (default: $200000)",
  141.  "END",        "/N", "-e", "set end of fast memory (default: $400000)",
  142.  "TO",         "/K", "-o", "write relocated A1000 kickload file",
  143.  "NORESET",    "/S", "-c", "load kickstart file but don't reboot",
  144.  NULL, NULL, NULL, NULL
  145. };
  146.  
  147.  
  148. void main(int argc, char *argv[])
  149. {
  150.   char *kickfile= "DEVS:Kickstart";
  151.   char *outfile= (char *)NULL;
  152.   long startkick= 0x200000;
  153.   long fastend= 0x400000;
  154.   int reboot= 1;
  155.   int badopt= 0;
  156.  
  157.   if(argc>1)
  158.   {
  159.     while(--argc>0 && !badopt)
  160.     { char *arg= *++argv;
  161.       if(isalpha(*arg))
  162.       { char **aopt= &howtouse[0];
  163.         while(*aopt && stricmp(arg,*aopt))
  164.           aopt= &aopt[4];
  165.         if(*aopt) arg= aopt[2];
  166.       }
  167.  
  168.       if(*arg=='-')
  169.       {
  170.         switch(*++arg)
  171.         {
  172. /* -f */  case 'f': case 'F':
  173.             if(arg[1]) ++arg;
  174.             else arg= (--argc > 0) ? *(++argv) : (char *)0L;
  175.  
  176.             if(arg && *arg)
  177.               kickfile= arg;
  178.             else
  179.             { puts("Missing input filename after keyword");
  180.               badopt=1;
  181.             }
  182.             break;
  183. /* -o */  case 'o': case 'O':
  184.             if(arg[1]) ++arg;
  185.             else arg= (--argc > 0) ? *(++argv) : (char *)0L;
  186.  
  187.             if(arg && *arg)
  188.               outfile= arg;
  189.             else
  190.             { puts("Missing output filename after keyword");
  191.               badopt=1;
  192.             }
  193.             break;
  194.  
  195. /* -s */  case 's': case 'S':
  196.             if(arg[1]) ++arg;
  197.             else arg= (--argc > 0) ? *(++argv) : (char *)0L;
  198.  
  199.             if(arg && *arg)
  200.             { if(arg[0]=='$') arg= &arg[1];
  201.               else if(arg[0]=='0' && (arg[1]=='x' || arg[1]=='X'))
  202.                 arg=&arg[2];
  203.               sscanf(arg,"%lx",&startkick);
  204.               if(startkick & 1)
  205.               { puts("Address error.");
  206.                 badopt=1;
  207.               }
  208.               if(startkick < 0x200000)
  209.               { puts("Can't load Kickstart into CHIP memory.");
  210.                 badopt=1;
  211.               }
  212.             }
  213.             else
  214.             { puts("Missing address after keyword");
  215.               badopt=1;
  216.             }
  217.             break;
  218. /* -e */  case 'e': case 'E':
  219.             if(arg[1]) ++arg;
  220.             else arg= (--argc > 0) ? *(++argv) : (char *)0L;
  221.  
  222.             if(arg && *arg)
  223.             { if(arg[0]=='$') arg= &arg[1];
  224.               else if(arg[0]=='0' && (arg[1]=='x' || arg[1]=='X'))
  225.                 arg=&arg[2];
  226.               sscanf(arg,"%lx",&fastend);
  227.               if(fastend & 1)
  228.               { puts("Address error.");
  229.                 badopt=1;
  230.               }
  231.             }
  232.             else
  233.             { puts("Missing address after keyword");
  234.               badopt=1;
  235.             }
  236.             break;
  237. /* -c */  case 'c': case 'C':
  238.             reboot= 0;
  239.             break;
  240.           default:
  241.             printf("bad option -%c.\n",*arg);
  242.             badopt=1;
  243.             break;
  244.         }
  245.       }
  246.       else if(*arg=='?')
  247.       { char **usage= &howtouse[0];
  248.         while(*usage)
  249.         { printf("%s%s,",usage[0],usage[1]);
  250.           usage= &usage[4];
  251.         }
  252.         printf("\b:\n\n");
  253.         usage= &howtouse[0];
  254.         while(*usage)
  255.         { printf("%-10s or '%s'  %s\n",usage[0],usage[2],usage[3]);
  256.           usage= &usage[4];
  257.         }
  258.         exit(0);
  259.       }
  260.       else strcpy(kickfile,arg);
  261.     }
  262.  
  263.     if(!badopt)
  264.     { int freeme=1;
  265.  
  266.       long *ptr= (long *)AllocMem(KICKSIZE,MEMF_PUBLIC);
  267.       if(!ptr && AvailMem(MEMF_FAST)==0)
  268.       { ptr=(long *)0x200000;
  269.         freeme=0;
  270.       }
  271.  
  272.       if(ptr)
  273.       { if(kickload(kickfile,(long)ptr))
  274.         { 
  275.           reloc((char *)ptr,startkick);
  276.           patch((long)ptr,startkick,startkick+0x040000,fastend,0x000000);
  277.           ptr[0x3fe00>>2]= checksum(&ptr[0x00000>>2],256*1024);
  278.           ptr[0x7fe00>>2]= checksum(&ptr[0x40000>>2],256*1024);
  279.           if(outfile && *outfile)
  280.             (void)kicksave(outfile,(long)ptr);
  281.           if(reboot) reset((long)ptr,startkick);
  282.         }
  283.         else badopt=1;
  284.         if(freeme) FreeMem(ptr,KICKSIZE);
  285.       }
  286.       else puts("Not enough memory!");
  287.     }
  288.   }
  289.   else /* no args */
  290.   { puts(BANNER);
  291.     puts("(c)Copyright 1992-93 by Tobias Ferber, All Rights Reserved");
  292.     puts("Refer to YKICK.DOC for options.  ? for AmigaDOS help");
  293.   }
  294.   exit(badopt?20:0);
  295. }
  296.